/*
  S.M.A.C.K - An operating system kernel
  Copyright (C) 2010,2011 Mattias Holm and Kristian Rietveld
  For licensing and a full list of authors of the kernel, see the files
  COPYING and AUTHORS.
*/

#ifndef KERNEL__SYNC_H
#define KERNEL__SYNC_H

#include <stdbool.h>
#include <stddef.h>

#include <process.h>
#include <list.h>

typedef struct {
  volatile int flag;
} spinlock_t;

//! Static initialiser for spin lock, use this when declaring the lock
#define SPIN_INITIALISER { 0 }

//! Dynamic initialiser for spin lock, use this when allocating the lock on the heap
void spin_init(spinlock_t *spinlock);

//! Aquire a spinlock, will poll the lock until it is aquired.
//! \pre Interrupts must be enabled
void spin_lock(spinlock_t *spinlock);

//! Release a spinlock
void spin_unlock(spinlock_t *spinlock);

/*!
  Nested mutex
*/
typedef struct {
  spinlock_t lock; //!< Lock for the mutex itself
  proc_t *proc; //!< Process holding the lock
  proc_list_t block_list; //!< Processes being blocked by this mutex
  unsigned level; //!< Nest level of the mutex
} mutex_t;

//! Static initialiser of mutex, use this when statically allocating the mutex
#define MUTEX_INITIALISER { SPIN_INITIALISER, NULL, {NULL, NULL}, 0 }

//! Dynamic initialiser of mutex, use this when allocating the mutex from the heap
void mutex_init(mutex_t *mutex);

//! Aquire the mutex, will block until mutex is available
void mutex_lock(mutex_t *mutex);
//! Try to aquire a mutex
//! \result True if the mutex was aquired, false otherwise
bool mutex_try_lock(mutex_t *mutex);
void mutex_unlock(mutex_t *mutex);


void hw_sync_lock_release(volatile int *ptr);
int hw_sync_lock_acquire(volatile int *ptr, int val);

#endif /* ! KERNEL__SYNC_H */
